Skip to content

Validate key type in _new_public_key_x509_der() on 3.x#173

Merged
toddr merged 3 commits intocpan-authors:mainfrom
toddr-bot:koan.toddr.bot/validate-x509-der-key-type
Apr 23, 2026
Merged

Validate key type in _new_public_key_x509_der() on 3.x#173
toddr merged 3 commits intocpan-authors:mainfrom
toddr-bot:koan.toddr.bot/validate-x509-der-key-type

Conversation

@toddr-bot
Copy link
Copy Markdown
Contributor

@toddr-bot toddr-bot commented Apr 23, 2026

What

Add EVP_PKEY_get_base_id() != EVP_PKEY_RSA validation to _new_public_key_x509_der() for OpenSSL 3.x builds.

Why

On OpenSSL 3.x, d2i_PUBKEY_bio() accepts any key type (EC, DSA, etc.), unlike the pre-3.x d2i_RSA_PUBKEY_bio() which inherently rejects non-RSA keys. Without validation, a non-RSA DER key is stored in the rsaData struct, leading to a corrupt object that fails unpredictably on subsequent operations.

The PEM-based _load_rsa_key() already has this guard (line 401) — this closes the same gap for the DER code path.

How

Added the same #if OPENSSL_VERSION_NUMBER >= 0x30000000L / EVP_PKEY_get_base_id() pattern from _load_rsa_key(). On mismatch, frees the key and croaks with "The key loaded is not an RSA key".

Two commits:

  1. Failing test — demonstrates the vulnerability by passing an EC public key in X.509 DER format to _new_public_key_x509_der() directly
  2. Fix — adds the guard, test now passes

Testing

  • New tests in t/der.t (tests 23-24): EC DER key rejected with clear error
  • Full suite: 652 tests across 23 files — all pass

🤖 Generated with Claude Code


Quality Report

Changes: 5 files changed, 72 insertions(+), 41 deletions(-)

Code scan: clean

Tests: passed (OK)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

toddr-bot and others added 2 commits April 23, 2026 12:32
On OpenSSL 3.x, d2i_PUBKEY_bio() accepts any key type (EC, DSA, etc.)
but _new_public_key_x509_der() has no type validation, unlike
_load_rsa_key() which checks EVP_PKEY_get_base_id(). This test
demonstrates the gap: an EC public key in X.509 DER format is
silently accepted, creating a corrupt rsaData object.

The test intentionally fails against the current code to document
the vulnerability before the fix is applied.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On OpenSSL 3.x, d2i_PUBKEY_bio() accepts any key type (EC, DSA,
etc.), unlike the pre-3.x d2i_RSA_PUBKEY_bio() which only accepts
RSA keys. Without validation, a non-RSA DER key would be stored in
the rsaData struct, leading to corrupt state and confusing failures
on subsequent operations.

Add the same EVP_PKEY_get_base_id() != EVP_PKEY_RSA guard already
present in _load_rsa_key() (line 401) to give a clear "not an RSA
key" error at load time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@timlegge
Copy link
Copy Markdown
Member

@toddr-bot the check needs to be:

like($@, qr/not an RSA key|ASN1|expecting an rsa key/i,

so that it works on Bullseye

On pre-3.x OpenSSL, d2i_RSA_PUBKEY_bio() rejects EC keys with
"expecting an rsa key" rather than "not an RSA key" (our croak) or
an ASN1 error. Add this variant to the regex so the test passes
across all supported OpenSSL versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@timlegge timlegge marked this pull request as ready for review April 23, 2026 13:57
Comment thread RSA.xs
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (EVP_PKEY_get_base_id(pkey) != EVP_PKEY_RSA) {
EVP_PKEY_free(pkey);
croak("The key loaded is not an RSA key");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this leak any SVs as we croak here?

@toddr toddr merged commit 508d59a into cpan-authors:main Apr 23, 2026
28 checks passed
@toddr-bot toddr-bot deleted the koan.toddr.bot/validate-x509-der-key-type branch April 23, 2026 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants